
# Constants
SHELL := $(SHELL) -e
default: all

include ../../mk/spksrc.common.mk

### Include common rules
include ../../mk/spksrc.common-rules.mk

# Configure the included makefiles
URLS                       = $(TC_DIST_SITE)/$(TC_DIST_NAME)
NAME                       = $(TC_NAME)
COOKIE_PREFIX              = 
ifneq ($(strip $(TC_DIST_FILE)),)
LOCAL_FILE                 = $(TC_DIST_FILE)
# download.mk uses PKG_DIST_FILE
PKG_DIST_FILE              = $(TC_DIST_FILE)
else
LOCAL_FILE                 = $(TC_DIST_NAME)
endif
DISTRIB_DIR                = $(TOOLCHAIN_DIR)/$(TC_VERS)
DIST_FILE                  = $(DISTRIB_DIR)/$(LOCAL_FILE)
DIST_EXT                   = $(TC_EXT)
TC_LOCAL_VARS_MK           = $(WORK_DIR)/tc_vars.mk
TC_LOCAL_VARS_CMAKE        = $(WORK_DIR)/tc_vars.cmake
TC_LOCAL_VARS_MESON_CROSS  = $(WORK_DIR)/tc_vars.meson-cross
TC_LOCAL_VARS_MESON_NATIVE = $(WORK_DIR)/tc_vars.meson-native

ifneq ($(strip $(ARCH)),)
ARCH_SUFFIX := -$(ARCH)-$(TCVERSION)
else
ARCH_SUFFIX :=
endif

#####

include ../../mk/spksrc.directories.mk

# Include ross-rust-env.mk to generate install its toolchain
include ../../mk/spksrc.cross-rust-env.mk

# Include cross-cmake-env.mk to generate its toolchain file
include ../../mk/spksrc.cross-cmake-env.mk

# Include cross-meson-env.mk to generate its toolchain file
include ../../mk/spksrc.cross-meson-env.mk

#####

RUN = cd $(WORK_DIR)/$(TC_TARGET) && env $(ENV)

include ../../mk/spksrc.depend.mk

download:
include ../../mk/spksrc.download.mk

checksum: download
include ../../mk/spksrc.checksum.mk

extract: checksum
include ../../mk/spksrc.extract.mk

fix: extract
include ../../mk/spksrc.tc-fix.mk

patch: fix
include ../../mk/spksrc.patch.mk

vers: patch
include ../../mk/spksrc.tc-vers.mk

flag: vers
include ../../mk/spksrc.tc-flags.mk

rustc: flag
include ../../mk/spksrc.tc-rust.mk

# Define _all as a real target that does the work
.PHONY: _all
_all: rustc depend $(TC_LOCAL_VARS_CMAKE) $(TC_LOCAL_VARS_MESON_CROSS) $(TC_LOCAL_VARS_MESON_NATIVE) $(TC_LOCAL_VARS_MK)

# all wraps _all with logging
.PHONY: all
.DEFAULT_GOAL := all

all:
	@bash -o pipefail -c ' \
	  mkdir -p $(WORK_DIR) ; \
	  $(MSG) $$(printf "%s MAKELEVEL: %02d, PARALLEL_MAKE: %s, ARCH: %s, NAME: %s\n" "$$(date +%Y%m%d-%H%M%S)" $(MAKELEVEL) "$(PARALLEL_MAKE)" "$(or $(lastword $(subst -, ,$(TC_NAME))),$(TC_ARCH))-$(TC_VERS)" "toolchain") | tee --append $(STATUS_LOG) ; \
	   if [ -z "$$LOGGING_ENABLED" ]; then \
	      export LOGGING_ENABLED=1 ; \
	      { \
	        $(MAKE) -f $(firstword $(MAKEFILE_LIST)) _all ; \
	      } > >(tee --append $(DEFAULT_LOG)) 2>&1 ; \
	   else \
	      $(MAKE) -f $(firstword $(MAKEFILE_LIST)) _all ; \
	   fi \
	' || { \
	   $(MSG) $$(printf "%s MAKELEVEL: %02d, PARALLEL_MAKE: %s, ARCH: %s, NAME: %s - FAILED\n" "$$(date +%Y%m%d-%H%M%S)" $(MAKELEVEL) "$(PARALLEL_MAKE)" "$(or $(lastword $(subst -, ,$(TC_NAME))),$(TC_ARCH))-$(TC_VERS)" "toolchain") | tee --append $(STATUS_LOG) ; \
	   exit 1 ; \
	}

.PHONY: $(TC_LOCAL_VARS_MK)
$(TC_LOCAL_VARS_MK):
	env $(MAKE) --no-print-directory tc_vars > $@ 2>/dev/null;

.PHONY: $(TC_LOCAL_VARS_CMAKE)
$(TC_LOCAL_VARS_CMAKE): 
	env $(MAKE) --no-print-directory cmake_vars > $@ 2>/dev/null;

.PHONY: $(TC_LOCAL_VARS_MESON_CROSS)
$(TC_LOCAL_VARS_MESON_CROSS): 
	env $(MAKE) --no-print-directory meson_cross_vars > $@ 2>/dev/null;

.PHONY: $(TC_LOCAL_VARS_MESON_NATIVE)
$(TC_LOCAL_VARS_MESON_NATIVE): 
	env $(MAKE) --no-print-directory meson_native_vars > $@ 2>/dev/null;

.PHONY: cmake_vars
cmake_vars:
	@echo "# the name of the target operating system" ; \
	echo "set(CMAKE_SYSTEM_NAME $(CMAKE_SYSTEM_NAME))" ; \
	echo
	@echo "# define target processor" ; \
	echo "set(CMAKE_SYSTEM_PROCESSOR $(CMAKE_SYSTEM_PROCESSOR))"
ifneq ($(strip $(CROSS_COMPILE_ARM)),)
	@echo "set(CROSS_COMPILE_ARM $(CROSS_COMPILE_ARM))"
endif
ifneq ($(strip $(CMAKE_ARCH)),)
	@echo "set(ARCH $(CMAKE_ARCH))"
endif
	@echo
	@echo "# Disable developer warnings" ; \
	echo 'set(CMAKE_SUPPRESS_DEVELOPER_WARNINGS ON CACHE BOOL "Disable developer warnings")'
	@echo
	@echo "# define toolchain location (used with CMAKE_TOOLCHAIN_FILE_PKG)" ; \
	echo "set(_CMAKE_TOOLCHAIN_LOCATION $(_CMAKE_TOOLCHAIN_LOCATION))" ; \
	echo "set(_CMAKE_TOOLCHAIN_PREFIX $(_CMAKE_TOOLCHAIN_PREFIX))" ; \
	echo
	@echo "# define cross-compilers and tools to use" ; \
	for tool in $(TOOLS) ; \
	do \
	  target=$$(echo $${tool} | sed 's/\(.*\):\(.*\)/\1/' | tr [:lower:] [:upper:] ) ; \
	  source=$$(echo $${tool} | sed 's/\(.*\):\(.*\)/\2/' ) ; \
	  if [ "$${target}" = "CC" ] ; then \
	    printf "set(%-25s %s)\n" CMAKE_C_COMPILER $(WORK_DIR)/$(TC_TARGET)/bin/$(TC_PREFIX)$${source} ; \
	  elif [ "$${target}" = "CPP" -o "$${target}" = "CXX" ] ; then \
	    printf "set(%-25s %s)\n" CMAKE_$${target}_COMPILER $(WORK_DIR)/$(TC_TARGET)/bin/$(TC_PREFIX)$${source} ; \
	  elif [ "$${target}" = "LD" ] ; then \
	    printf "set(%-25s %s)\n" CMAKE_LINKER $(WORK_DIR)/$(TC_TARGET)/bin/$(TC_PREFIX)$${source} ; \
	  elif [ "$${target}" = "LDSHARED" ] ; then \
	    printf "set(%-25s %s)\n" CMAKE_SHARED_LINKER_FLAGS $$(echo $${source} | cut -f2 -d' ') ; \
	  elif [ "$${target}" = "FC" ] ; then \
	    printf "set(%-25s %s)\n" CMAKE_Fortran_COMPILER $(WORK_DIR)/$(TC_TARGET)/bin/$(TC_PREFIX)$$(echo $${source} | cut -f2 -d' ') ; \
	  else \
	    printf "set(%-25s %s)\n" CMAKE_$${target} $(WORK_DIR)/$(TC_TARGET)/bin/$(TC_PREFIX)$${source} ; \
	  fi ; \
	done ; \
	echo
	@echo "# define 'build' compilers and tools to use" ; \
	for tool in $(TOOLS) ; \
	do \
	  target=$$(echo $${tool} | sed 's/\(.*\):\(.*\)/\1/' | tr [:lower:] [:upper:] ) ; \
	  source=$$(echo $${tool} | sed 's/\(.*\):\(.*\)/\2/' ) ; \
	  if [ "$${target}" = "CC" ] ; then \
	    printf "set(%-35s %s)\n" CMAKE_C_COMPILER_FOR_BUILD $$(which $${source}) ; \
	  elif [ "$${target}" = "CPP" -o "$${target}" = "CXX" ] ; then \
	    printf "set(%-35s %s)\n" CMAKE_$${target}_COMPILER_FOR_BUILD $$(which $${source}) ; \
	  elif [ "$${target}" = "LD" ] ; then \
	    printf "set(%-35s %s)\n" CMAKE_LINKER_FOR_BUILD $$(which $${source}) ; \
	  elif [ "$${target}" = "LDSHARED" ] ; then \
	    printf "set(%-25s %s)\n" CMAKE_SHARED_LINKER_FLAGS_FOR_BUILD $$(echo $${source} | cut -f2 -d' ') ; \
	  elif [ "$${target}" = "FC" ] ; then \
	    printf "set(%-35s %s)\n" CMAKE_Fortran_COMPILER_FOR_BUILD $$(which $${source}) ; \
	  else \
	    printf "set(%-35s %s)\n" CMAKE_$${target}_FOR_BUILD $$(which $${source}) ; \
	  fi ; \
	done ; \
	echo
	@echo "# where is the target environment located" ; \
	echo "set(CMAKE_FIND_ROOT_PATH $(CMAKE_FIND_ROOT_PATH))" ; \
	echo ; \
	echo "# adjust the default behavior of the FIND_XXX() commands:" ; \
	echo "# search programs in the host environment" ; \
	echo "set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM $(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM))" ; \
	echo ; \
	echo "# search headers and libraries in the target environment" ; \
	echo "set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY $(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY))" ; \
	echo "set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE $(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE))"
	@echo ; \
	echo "# Rust compiler and Cargo" ; \
	echo "set(CARGO  $(RUSTUP_HOME)/toolchains/stable-x86_64-unknown-linux-gnu/bin/cargo)"
ifeq ($(TC_RUSTUP_TOOLCHAIN),stable)
	@echo "set(RUSTC  $(RUSTUP_HOME)/toolchains/$(TC_RUSTUP_TOOLCHAIN)-x86_64-unknown-linux-gnu/bin/rustc)"
else
	@echo "set(RUSTC  $(RUSTUP_HOME)/toolchains/$(TC_RUSTUP_TOOLCHAIN)/bin/rustc)"
endif
	@echo ; \
	echo "# Cross target triple" ; \
	echo "set(RUST_TARGET  $(RUST_TARGET))" ; \
	echo ; \
	echo "# Rust linker and AR" ; \
	echo "set(RUST_LINKER  \$${CMAKE_C_COMPILER})" ; \
	echo "set(RUST_AR      \$${CMAKE_AR})" ; \
	echo ; \
	echo "# Export Rust environment for Cargo builds" ; \
	echo "set(ENV{RUSTC} \$${RUSTC})" ; \
	echo "set(ENV{CARGO} \$${CARGO})" ; \
	echo "set(ENV{CARGO_BUILD_TARGET} \$${RUST_TARGET})" ; \
	echo "set(ENV{CARGO_TARGET_$(shell echo $(RUST_TARGET) | tr - _ | tr a-z A-Z)_LINKER} \$${RUST_LINKER})" ; \
	echo "set(ENV{CARGO_TARGET_$(shell echo $(RUST_TARGET) | tr - _ | tr a-z A-Z)_AR} \$${RUST_AR})" ; \
	echo "set(ENV{CARGO_TARGET_$(shell echo $(RUST_TARGET) | tr - _ | tr a-z A-Z)_RUSTFLAGS} $(TC_EXTRA_RUSTFLAGS))"

.PHONY: meson_cross_vars
meson_cross_vars:
	@echo "[host_machine]" ; \
	echo "system = 'linux'" ; \
	echo "cpu_family = '$(MESON_HOST_CPU_FAMILY)'" ; \
	echo "cpu = '$(MESON_HOST_CPU)'" ; \
	echo "endian = '$(MESON_HOST_ENDIAN)'"
	@echo
	@echo "[binaries]" ; \
	for tool in $(TOOLS) ; \
	do \
	  target=$$(echo $${tool} | sed 's/\(.*\):\(.*\)/\1/' ) ; \
	  source=$$(echo $${tool} | sed 's/\(.*\):\(.*\)/\2/' ) ; \
	  if [ "$${target}" = "cpp" ]; then \
	    echo "# Ref: https://mesonbuild.com/Machine-files.html#binaries" ; \
	    echo "$${target} = '$(WORK_DIR)/$(TC_TARGET)/bin/$(TC_PREFIX)g++'" ; \
	  elif [ "$${target}" = "fc" ]; then \
	    echo "fortran = '$(WORK_DIR)/$(TC_TARGET)/bin/$(TC_PREFIX)$${source}'" ; \
	  elif [ "$${target}" = "cc" ]; then \
	    echo "c = '$(WORK_DIR)/$(TC_TARGET)/bin/$(TC_PREFIX)$${source}'" ; \
	    echo "$${target} = '$(WORK_DIR)/$(TC_TARGET)/bin/$(TC_PREFIX)$${source}'" ; \
	  else \
	    echo "$${target} = '$(WORK_DIR)/$(TC_TARGET)/bin/$(TC_PREFIX)$${source}'" ; \
	  fi ; \
	done
	@echo "cargo = '$(RUSTUP_HOME)/toolchains/stable-x86_64-unknown-linux-gnu/bin/cargo'"
ifeq ($(TC_RUSTUP_TOOLCHAIN),stable)
	@echo "rust = '$(RUSTUP_HOME)/toolchains/$(TC_RUSTUP_TOOLCHAIN)-x86_64-unknown-linux-gnu/bin/rustc'"
else
	@echo "rust = '$(RUSTUP_HOME)/toolchains/$(TC_RUSTUP_TOOLCHAIN)/bin/rustc'"
endif

.PHONY: meson_native_vars
meson_native_vars:
	@echo "[binaries]"
	@for tool in $(TOOLS) ; \
	do \
	  target=$$(echo $${tool} | sed 's/\(.*\):\(.*\)/\1/' ) ; \
	  source=$$(echo $${tool} | sed 's/\(.*\):\(.*\)/\2/' ) ; \
	  if [ "$${target}" = "cc" ]; then \
	    echo "c = '$$(which $${source})'" ; \
	    echo "$${target} = '$$(which $${source})'" ; \
	  elif [ "$${target}" = "fc" ]; then \
	    echo "fortran = '$$(which $${source})'" ; \
	  elif [ "$${target}" = "ldshared" ]; then \
	    echo "$${target} = '$$(which gcc) -shared'" ; \
	  else \
	    echo "$${target} = '$$(which $${source})'" ; \
	  fi ; \
	done
	@echo "g-ir-compiler = '$$(which g-ir-compiler)'" ; \
        echo "g-ir-generate = '$$(which g-ir-generate)'" ; \
        echo "g-ir-scanner = '$$(which g-ir-scanner)'"

.PHONY: tc_vars
tc_vars: flag
	@echo TC_ENV := ; \
	echo TC_ENV += SYSROOT=\"$(WORK_DIR)/$(TC_TARGET)/$(TC_SYSROOT)\" ; \
	for tool in $(TOOLS) ; \
	do \
	  target=$$(echo $${tool} | sed 's/\(.*\):\(.*\)/\1/' | tr [:lower:] [:upper:] ) ; \
	  source=$$(echo $${tool} | sed 's/\(.*\):\(.*\)/\2/' ) ; \
	  echo TC_ENV += $${target}=\"$(WORK_DIR)/$(TC_TARGET)/bin/$(TC_PREFIX)$${source}\" ; \
	  if [ "$${target}" = "CC" ] ; then \
	    gcc_version=$$(eval $$(echo $(WORK_DIR)/$(TC_TARGET)/bin/$(TC_PREFIX)$${source} -dumpversion) 2>/dev/null || true) ; \
	  fi ; \
	done ; \
	echo TC_ENV += CFLAGS=\"$(CFLAGS) $$\(GCC_DEBUG_FLAGS\) $$\(ADDITIONAL_CFLAGS\)\" ; \
	echo TC_ENV += CPPFLAGS=\"$(CPPFLAGS) $$\(GCC_DEBUG_FLAGS\) $$\(ADDITIONAL_CPPFLAGS\)\" ; \
	echo TC_ENV += CXXFLAGS=\"$(CXXFLAGS) $$\(GCC_DEBUG_FLAGS\) $$\(ADDITIONAL_CXXFLAGS\)\" ; \
	if [ -n "$(TC_HAS_FORTRAN)" ]; then \
	   echo TC_ENV += FFLAGS=\"$(FFLAGS) $$\(GCC_DEBUG_FLAGS\) $$\(ADDITIONAL_FFLAGS\)\" ; \
	fi ; \
	echo TC_ENV += LDFLAGS=\"$(LDFLAGS) $$\(ADDITIONAL_LDFLAGS\)\" ; \
	echo TC_ENV += RUSTFLAGS=\"$(RUSTFLAGS) $$\(ADDITIONAL_RUSTFLAGS\)\" ; \
	echo TC_ENV += CARGO_HOME=\"$(realpath $(CARGO_HOME))\" ; \
	echo TC_ENV += RUSTUP_HOME=\"$(realpath $(RUSTUP_HOME))\" ; \
	echo TC_ENV += RUSTUP_TOOLCHAIN=\"$(TC_RUSTUP_TOOLCHAIN)\" ; \
	echo TC_ENV += CARGO_BUILD_TARGET=\"$(RUST_TARGET)\" ; \
	echo TC_ENV += CARGO_TARGET_$(shell echo $(RUST_TARGET) | tr - _ | tr a-z A-Z)_AR=\"$(WORK_DIR)/$(TC_TARGET)/bin/$(TC_PREFIX)ar\" ; \
	echo TC_ENV += CARGO_TARGET_$(shell echo $(RUST_TARGET) | tr - _ | tr a-z A-Z)_LINKER=\"$(WORK_DIR)/$(TC_TARGET)/bin/$(TC_PREFIX)gcc\" ; \
	echo TC_ENV += CARGO_TARGET_$(shell echo $(RUST_TARGET) | tr - _ | tr a-z A-Z)_RUSTFLAGS=\"$(TC_EXTRA_RUSTFLAGS)\" ; \
	echo TC_CONFIGURE_ARGS := --host=$(TC_TARGET) --build=i686-pc-linux ; \
	echo TC_TYPE := $(TC_TYPE) ; \
	echo TC_SYSROOT := $(WORK_DIR)/$(TC_TARGET)/$(TC_SYSROOT) ; \
	echo TC_TARGET := $(TC_TARGET) ; \
	echo TC_PREFIX := $(TC_PREFIX) ; \
	echo TC_PATH := $(WORK_DIR)/$(TC_TARGET)/bin/ ; \
	echo CFLAGS := $(CFLAGS) $$\(GCC_DEBUG_FLAGS\) $$\(ADDITIONAL_CFLAGS\) ; \
	echo CPPFLAGS := $(CPPFLAGS) $$\(GCC_DEBUG_FLAGS\) $$\(ADDITIONAL_CPPFLAGS\) ; \
	echo CXXFLAGS := $(CXXFLAGS) $$\(GCC_DEBUG_FLAGS\) $$\(ADDITIONAL_CXXFLAGS\) ; \
	if [ -n "$(TC_HAS_FORTRAN)" ]; then \
	   echo FFLAGS := $(FFLAGS) $$\(GCC_DEBUG_FLAGS\) $$\(ADDITIONAL_FFLAGS\) ; \
	fi ; \
	echo LDFLAGS := $(LDFLAGS) $$\(ADDITIONAL_LDFLAGS\) ; \
	echo RUSTFLAGS := $(RUSTFLAGS) $$\(ADDITIONAL_RUSTFLAGS\) ; \
	echo RUST_TARGET := $(RUST_TARGET) ; \
	echo TC_INCLUDE := $(TC_INCLUDE) ; \
	echo TC_LIBRARY := $(TC_LIBRARY) ; \
	echo TC_EXTRA_CFLAGS := $(TC_EXTRA_CFLAGS) ; \
	echo TC_EXTRA_RUSTFLAGS := $(TC_EXTRA_RUSTFLAGS) ; \
	echo TC_VERS := $(TC_VERS) ; \
	echo TC_BUILD := $(TC_BUILD) ; \
	echo TC_OS_MIN_VER := $(TC_OS_MIN_VER) ; \
	echo TC_ARCH := $(TC_ARCH) ; \
	echo TC_GCC := $${gcc_version} ; \
	echo TC_GLIBC := $(TC_GLIBC)
# Add "+" to EXTRAVERSION for kernels version >= 4.4
ifeq ($(call version_ge, ${TC_KERNEL}, 4.4),1)
	@echo TC_KERNEL := $(TC_KERNEL)+
else
	@echo TC_KERNEL := $(TC_KERNEL)
endif

### For make digests
include ../../mk/spksrc.generate-digests.mk
